package com.rfid.rfidbluetooth.manager;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.content.Context;
import android.os.ParcelUuid;
import android.util.Log;

import com.rfid.base.util.ByteUtils;
import com.rfid.rfidbluetooth.CmdBuild;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.UUID;

import static com.rfid.rfidbluetooth.CmdBuild.CMD_REQ_RFID;

public enum  BleServerManager {

    INSTANCE;
    BluetoothLeAdvertiser mBluetoothLeAdvertiser;
    UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    UUID duuid = UUID.fromString("00001102-0000-1000-8000-00805F9B34FB");

    BluetoothGattServer mBluetoothGattServer;
    BluetoothGattCharacteristic characteristicRead;
    static String TAG = "BleServerManger";

    public void startServer(Context context) {
        //广播设置(必须)
        AdvertiseSettings settings = new AdvertiseSettings.Builder()
                .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) //广播模式: 低功耗,平衡,低延迟
                .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) //发射功率级别: 极低,低,中,高
                .setTimeout(0)
                .setConnectable(true) //能否连接,广播分为可连接广播和不可连接广播
                .build();

//广播数据(必须，广播启动就会发送)
        AdvertiseData advertiseData = new AdvertiseData.Builder()
                .setIncludeDeviceName(true) //包含蓝牙名称
                .setIncludeTxPowerLevel(true) //包含发射功率级别
                .addManufacturerData(1, "test ble".getBytes()) //设备厂商数据，自定义
                .build();

//扫描响应数据(可选，当客户端扫描时才发送)
        AdvertiseData scanResponse = new AdvertiseData.Builder()
                .addManufacturerData(2, new byte[]{66, 66}) //设备厂商数据，自定义
                .addServiceUuid(new ParcelUuid(uuid)) //服务UUID
//                .addServiceData(new ParcelUuid(UUID_SERVICE), new byte[]{2}) //服务数据，自定义
                .build();

        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

// ============启动BLE蓝牙广播(广告) ===============
        mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
        mBluetoothLeAdvertiser.startAdvertising(settings, advertiseData, scanResponse, new AdvertiseCallback() {
            @Override
            public void onStartSuccess(AdvertiseSettings settingsInEffect) {
                System.out.println("onStartSuccess");
            }

            @Override
            public void onStartFailure(int errorCode) {
                System.out.println("onStartFailure errorCode = " + errorCode);
            }
        });

        configService(context);
    }

    private void configService(Context context) {
        BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        // 注意：必须要开启可连接的BLE广播，其它设备才能发现并连接BLE服务端!
// =============启动BLE蓝牙服务端======================================
        BluetoothGattService service = new BluetoothGattService(uuid, BluetoothGattService.SERVICE_TYPE_PRIMARY);

//添加可读+通知characteristic
        characteristicRead = new BluetoothGattCharacteristic(uuid,BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY | BluetoothGattCharacteristic.PROPERTY_WRITE , BluetoothGattCharacteristic.PERMISSION_READ|BluetoothGattCharacteristic.PERMISSION_WRITE);
        characteristicRead.addDescriptor(new BluetoothGattDescriptor(duuid, BluetoothGattCharacteristic.PERMISSION_WRITE));
        service.addCharacteristic(characteristicRead);

//添加可写characteristic
//        BluetoothGattCharacteristic characteristicWrite = new BluetoothGattCharacteristic(uuid, BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_WRITE);
//        service.addCharacteristic(characteristicWrite);

        if (bluetoothManager != null){
            mBluetoothGattServer = bluetoothManager.openGattServer(context,mBluetoothGattServerCallback);
        }

        mBluetoothGattServer.addService(service);
    }

    private BluetoothGattServerCallback mBluetoothGattServerCallback= new BluetoothGattServerCallback() {

        /**
         * 1.连接状态发生变化时
         */
        @Override
        public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
            Log.e(TAG, String.format("1.onConnectionStateChange：device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("1.onConnectionStateChange：status = %s, newState =%s ", status, newState));
        }

        @Override
        public void onServiceAdded(int status, BluetoothGattService service) {
            Log.e(TAG, String.format("onServiceAdded：status = %s", status));
        }

        @Override
        public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
            Log.e(TAG, String.format("onCharacteristicReadRequest：device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("onCharacteristicReadRequest：requestId = %s, offset = %s", requestId, offset));

            mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());

        }

        /**
         * 3. onCharacteristicWriteRequest,接收具体的字节
         */
        @Override
        public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes) {
            Log.e(TAG, String.format("3.onCharacteristicWriteRequest：device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("3.onCharacteristicWriteRequest：requestId = %s, preparedWrite=%s, responseNeeded=%s, offset=%s, value=%s", requestId, preparedWrite, responseNeeded, offset, new String(requestBytes)));

            mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, requestBytes);

            ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBytes);
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            int cmd = 0;
            try {
                cmd = dataInputStream.readShort();
                if (cmd == CMD_REQ_RFID) {
                    int cell = dataInputStream.read();
                    int ph = dataInputStream.read();
                    int port = dataInputStream.read();
                    int len = dataInputStream.read();
                    byte buffer[] = new byte[len];
                    if (len > 0) {
                        dataInputStream.readFully(buffer,0,len);
                    }
                    int m = dataInputStream.read();
                    byte data[] = CmdBuild.mockResponEpcs(ph);
                    System.out.println(ByteUtils.bytesToHexString(data));
                    characteristic.setValue(data);
                    boolean success = mBluetoothGattServer.notifyCharacteristicChanged(device, characteristic, false);
                    if (success) {
                        Log.d(TAG, "Notification sent successfully.");
                    } else {
                        Log.e(TAG, "Failed to send notification.");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("listenning cmd = " + Integer.toHexString(cmd&0XFFFF));
        }

        /**
         * 2.描述被写入时，在这里执行 bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS...  收，触发 onCharacteristicWriteRequest
         */
        @Override
        public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
            Log.e(TAG, String.format("2.onDescriptorWriteRequest：device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("2.onDescriptorWriteRequest：requestId = %s, preparedWrite = %s, responseNeeded = %s, offset = %s, value = %s,", requestId, preparedWrite, responseNeeded, offset, new String(value)));

            // now tell the connected device that this was all successfull
            mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
        }

        /**
         * 5.特征被读取。当回复响应成功后，客户端会读取然后触发本方法
         */
        @Override
        public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
            Log.e(TAG, String.format("onDescriptorReadRequest：device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("onDescriptorReadRequest：requestId = %s", requestId));

            mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null);
        }

        @Override
        public void onNotificationSent(BluetoothDevice device, int status) {
            super.onNotificationSent(device, status);
            Log.e(TAG, String.format("5.onNotificationSent：device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("5.onNotificationSent：status = %s", status));
        }

        @Override
        public void onMtuChanged(BluetoothDevice device, int mtu) {
            super.onMtuChanged(device, mtu);
            Log.e(TAG, String.format("onMtuChanged：mtu = %s", mtu));
        }

        @Override
        public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
            super.onExecuteWrite(device, requestId, execute);
            Log.e(TAG, String.format("onExecuteWrite：requestId = %s", requestId));
        }
    };


}
